/**
 * @author Tobias Boehm
 *
 * 09.06.2011
 */
package org.anddev.andengine.extension.tbsengine.message.server.ingame;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;

import org.anddev.andengine.extension.tbsengine.match.AbsServerMatch;
import org.anddev.andengine.extension.tbsengine.message.client.ClientMatchJoinLeaveRequestMessage;
import org.anddev.andengine.extension.tbsengine.message.server.AbsServerMatchMessage;
import org.anddev.andengine.extension.tbsengine.player.BasePlayer;

/**
 * This is an abstract class for a reply to an {@link ClientMatchJoinLeaveRequestMessage}
 * which is related to a running match. You should provide all necessary match 
 * data to recreate the match state on the client side to the reconnecting
 * player.
 * 
 * @author Tobias Boehm
 *
 * @param <ServerMatchClass> - Your implementation of {@link AbsServerMatch}
 */
public abstract class AbsServerMatchReconnectRequestReplyMessage<ServerMatchClass extends AbsServerMatch> extends
		AbsServerMatchMessage {

	public static enum ReconnectRequestAnswerReason{OK,MATCH_DOES_NOT_EXIST,NOT_MEMBER_OF_MATCH};
	
	/*
	 * ServerSide Data
	 */
	protected ServerMatchClass mMatch;
	
	/*
	 * Common Data
	 */
	protected ReconnectRequestAnswerReason mReason;
	protected boolean mAccepted;
		
	/*
	 * Client Side Data
	 */
	protected String mMapID;
	protected HashMap<Integer,BasePlayer> mGameStateIDplayerMap;
	protected HashMap<Integer,String> mGameStateIDfactionNameMap;
	protected HashMap<Integer,Integer> mGameStateIDteamIDmap;
	protected HashMap<Integer,Long> mGameStateIDrandomSeedMap;
	
	
	
	protected abstract void readMatchData(final DataInputStream pDataInputStream,
			  final HashMap<Integer, BasePlayer> pGameStateIDplayerMap,
			  final HashMap<Integer, String> pGameStateIDfactionNameMap,
			  final HashMap<Integer, Integer> pGameStateIDteamIDmap,
			  final HashMap<Integer, Long> pGameStateIDrandomSeed);

	protected abstract void writeMatchData(final DataOutputStream pDataOutputStream, final ServerMatchClass pMatch);
	
	/* (non-Javadoc)
	 * @see org.anddev.andengine.extension.multiplayer.protocol.adt.message.IMessage#getFlag()
	 */
	@Override
	public short getFlag() {
		
		return FLAG_SERVER_MATCH_RECONNECT_REQUEST_REPLY;
	}

	@Override
	protected void onReadTransmissonMatchData(DataInputStream pDataInputStream)
			throws IOException {

		this.mAccepted = pDataInputStream.readBoolean();
		
		this.mReason = ReconnectRequestAnswerReason.valueOf(pDataInputStream.readUTF());
				
		if(this.mAccepted){
					
			this.initMaps();
			
			this.readMatchData(pDataInputStream, this.mGameStateIDplayerMap, this.mGameStateIDfactionNameMap, this.mGameStateIDteamIDmap, this.mGameStateIDrandomSeedMap);
		}
	}
	
	@Override
	protected void onWriteTransmissonMatchData(
			DataOutputStream pDataOutputStream) throws IOException {

		pDataOutputStream.writeBoolean(this.mAccepted);
		
		pDataOutputStream.writeUTF(this.mReason.name());
		
		if(this.mAccepted){
		
			this.writeMatchData(pDataOutputStream, this.mMatch);
		}
	}

	protected void initMaps() {
		
		this.mGameStateIDplayerMap = new HashMap<Integer, BasePlayer>();
		this.mGameStateIDfactionNameMap = new HashMap<Integer, String>();
		this.mGameStateIDteamIDmap = new HashMap<Integer, Integer>();
		this.mGameStateIDrandomSeedMap = new HashMap<Integer, Long>();
	}
	
	public void setMatchInstance(ServerMatchClass pMatch) {
		super.setMatch(pMatch);
		
		this.mMatch = pMatch;
	}

	/**
	 * @return the mReason
	 */
	public ReconnectRequestAnswerReason getReason() {
		return mReason;
	}

	/**
	 * @param mReason the mReason to set
	 */
	public void setReason(ReconnectRequestAnswerReason mReason) {
		this.mReason = mReason;
	}

	/**
	 * @return the mAccepted
	 */
	public boolean isAccepted() {
		return mAccepted;
	}

	/**
	 * @param mAccepted the mAccepted to set
	 */
	public void setAccepted(boolean mAccepted) {
		this.mAccepted = mAccepted;
	}

	/**
	 * @return the mMapID
	 */
	public String getMapID() {
		return mMapID;
	}

	/**
	 * @return the mGameStateIDplayerMap
	 */
	public HashMap<Integer, BasePlayer> getGameStateIDplayerMap() {
		return mGameStateIDplayerMap;
	}

	/**
	 * @return the mGameStateIDfactionNameMap
	 */
	public HashMap<Integer, String> getGameStateIDfactionNameMap() {
		return mGameStateIDfactionNameMap;
	}

	/**
	 * @return the mGameStateIDteamIDmap
	 */
	public HashMap<Integer, Integer> getGameStateIDteamIDmap() {
		return mGameStateIDteamIDmap;
	}

	/**
	 * @return the mGameStateIDrandomSeedMap
	 */
	public HashMap<Integer, Long> getGameStateIDrandomSeedMap() {
		return mGameStateIDrandomSeedMap;
	}

}
